/**
 * 
 */
package com.netflexitysolutions.amazonws.sdb.orm.support;

import java.lang.reflect.ParameterizedType;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.netflexitysolutions.amazonws.sdb.Domain;
import com.netflexitysolutions.amazonws.sdb.orm.SimpleDBSession;
import com.netflexitysolutions.amazonws.sdb.orm.filter.Predicate;
import com.netflexitysolutions.amazonws.sdb.orm.filter.TypeFilter;
import com.netflexitysolutions.amazonws.sdb.orm.metadata.ItemMetadata;
import com.netflexitysolutions.amazonws.sdb.orm.metadata.SimpleDBMapping;

/**
 * Generic utility class that simplifies DAO development by 
 * automatically adding most common operations for each entity/domain class.
 * 
 * @author netflexity
 *
 */
public class SimpleDBDaoSupport<T> {

	protected Log logger = LogFactory.getLog(this.getClass());
	
    private Class<T> persistentClass;
    private SimpleDBSession session;
    protected Predicate<T> ALL;
    
    /**
     * Default constructor.
     */
    @SuppressWarnings("unchecked")
    public SimpleDBDaoSupport(SimpleDBSession session) {
    	setSession(session);
        this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        this.ALL = new TypeFilter<T>(persistentClass, getSession().getFactory().getMapping());
    }

    /**
     * @return
     */
    public Class<T> getPersistentClass() {
        return persistentClass;
    }

    /**
     * @return
     */
    public Domain getDomain(){
    	return getSession().getDomain(persistentClass);
    }
    
    /**
     * @return
     */
    public ItemMetadata getMetadata(){
    	return getSession().getMetadata(persistentClass);
    }
    
    /**
     * @return
     */
    public SimpleDBMapping getMapping(){
    	return getSession().getFactory().getMapping();
    }
    
    /**
     * @param entity
     * @return
     */
    public T save(T entity) {
        getSession().save(entity);
        return entity;
    }

    /**
     * @param entity
     * @return
     */
    public T update(T entity) {
    	getSession().save(entity);
        return entity;
    }

    /**
     * @param entity
     */
    public void delete(T entity) {
    	getSession().remove(entity);
    }

    /**
     * @param entity
     */
    public void populate(T entity) {
    	getSession().populate(entity);
    }
    
    /**
     * @return
     */
    public int countAll(){
    	Integer count = getSession().count(ALL);
    	return count == null ? 0 : count.intValue();
    }
    
    /**
     * @param id
     * @return
     */
    public T find(String id) {
        return (T) getSession().find(persistentClass, id);
    }
    
    /**
     * @param orderBy
     * @return
     */
    public Set<T> findAll(String... orderBy) {
        return (Set<T>) getSession().findAll(persistentClass, orderBy);
    }

	/**
	 * @return the session
	 */
	public SimpleDBSession getSession() {
		return session;
	}

	/**
	 * @param session the session to set
	 */
	public void setSession(SimpleDBSession session) {
		this.session = session;
	}
}
